/*
*autores: 
*	Luis Franco 		nº 12052
*	Ricardo Cabecinha	nº 12071
*
*CPS 2012
*Date: 06-02-2012
*This program creates N pseudo-random numbers
*
*Virtual Box - Virtual Machine: Linux Mint 11 2.6.38-8-generic
*
*processor	: 0
*vendor_id	: GenuineIntel
*cpu family	: 6
*model		: 23
*model name	: Intel(R) Core(TM)2 Duo CPU     T6600  @ 2.20GHz
*stepping	: 10
*cpu MHz		: 2108.307
*cache size	: 6144 KB
*address sizes	: 36 bits physical, 48 bits virtual
*
*note: the execution time have been taken including output time
*output: N[k] = randomized_number
*
*Execution times:
*10			Numbers: Code time 0.0000 seconds
*100		Numbers: Code time 0.0000 seconds
*1000		Numbers: Code time 0.0100 seconds
*10000		Numbers: Code time 0.1200 seconds
*100000 	Numbers: Code time 1.2900 seconds
*1000000	Numbers: Code time 13.9600 seconds
*
*/

#include <stdio.h>
#include <stdlib.h> /*required for random*/
#include <time.h>
/*use for randomize numbers from 0 to 9*/
#define MAX_RAND 10
/*Table size*/
#define TSIZE 1000

int getUserInputNumber();
void swap();
void fillTable();
unsigned int getNk(int p);

int table[TSIZE];
int z1, z2, z3, z4;

int main(int argc, char ** argv)
{
	clock_t t1, t2;
	/*variable that stores a pseudo-random between 0 and 999*/
	int p;
	/*iterator How many numbers to generate*/
	int nIter;
	unsigned int nk; //random number for k iteration
	int n; //iterator helper

	//ask user input?!
	 nIter = getUserInputNumber();
	

	/*srand: allows a given starting point
	*in the sequence to be choosen according to the value of seed
	*If is not called before rand() the value of seed is taken 
	*to be 1
	*/
	t1 = clock();
	srand(time(NULL));

	/*fills the table*/
	fillTable();

	
	/*random number 0 to 999*/
	p = (rand() % 1000);
	//printf("p=%d\n", p);

	/**/
	
	n = 1; //number iterator
	while (nIter > 0)
	{	
		//printf("p = %d\n", p);
		nk = getNk(p);
		printf("N[%d] = %d\n", n, nk); 
		nIter = nIter - 1;
		n = n + 1;
		/*recalculate p */
		p = z1 * 100 + z2 * 10 + z3;
		
		
	}

	t2 = clock();
	printf("Code time %.4lf seconds\n", (t2-t1)/(double)CLOCKS_PER_SEC);
	return 0;	

}

/*
*Function that handle user input
*returns user input if numeric
*else exit program
*/
int getUserInputNumber()
{
		int x;
		printf("Enter the number of random numbers: ");
		
		if (scanf("%d", &x) >= 1)
		{
			return x;
		}
		else
		{
			printf("Oops! That was no valid number! Try again...\n");
			exit(0);			
		}
}

/*
*Function that returns a 16 bit integer
*nK 16-bit positive integer randomized number
*1st 4 bits = z1
*2nd 4 bits = z2
*3rd 4 bits = z3
*last 4 bits = z4
*
*receave a random integer (p)
*calculates z1, z2, z3, z4
*
*/
unsigned int getNk(int p)
{
	
	//get z1
	if (p < 1000)
	{
		//p is always < 1000
		z1 = table[p];
		swap(p);
	}
	else
	{
		z1 = table[0];
		//swap(p);
	}
	//get z2
	if (p < 999)
	{
		z2 = table[p+1];
		swap(p+1);
	}
	else
	{
		z2 = table[0];
		//swap(p+1);
	}
	//get z3
	if (p < 998)
	{
		z3 = table[p+2];
		swap(p+2);
				
	}
	else
	{
		z3 = table[0];
		//swap(p+2);
	}
	//get z4	
	if (p < 997)
	{
		z4 = table[p+3];
		swap(p+3);
		
	}
	else
	{
		z4 = table[0];
		//swap(p+3);
	}
			
	/*Positive 16-bit integer*/
	unsigned int nk;
	nk = 0;
	/*
	*nK 16-bit integer randomized number
	*1st 4 bits = z1
	*2nd 4 bits = z2
	*3rd 4 bits = z3
	*last 4 bits = z4
	*/
	nk = ((z1 << 12) | (z2 << 8) | (z3 << 4) | z4);
	return nk;
}

/*
*function used to swap table[p] and table[0]
*/
void swap(int p)
{
	int tmp;
	tmp = table[0];
	table[0] = table[p];
	table[p] = tmp;
}

/*
*Function that creates a 1000 entry table
*Each position of table stores a random between 0 and 9
*every random number will occur the same number of times
*/
void fillTable()
{
	/*some itereator...used only for print*/
	int i;
	/*initialze counter array for generated numbers*/
	int genCount[10] = {0};
	/*used to check if table is completed*/
	int complete = 0;
	/*variable to store the random number*/
	int number;
	/*table iterator*/
	int tableit = 0;
		

	/*fills the table with random numbers from 0 to 9*/
	while(tableit < TSIZE)
	{
		/*Generates a random number*/
		number = (rand() % 10);
		/*Verifies is the random number appeared less then 100 times*/
		if(genCount[number] > 99)
			continue;
		/*add the number to the table*/
		table[tableit] = number;
		/*increment the occurences of the number*/
		genCount[number] = genCount[number] + 1;
		//printf("genCount[%i] = %i\n", number, genCount[number]);
		//printf("table= %i\n", tableit);
		/*move one position on the table*/
		tableit ++;
		
	}


}

